home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ASMVEG5.ZIP / ASMVEG5.TXT next >
Text File  |  1996-12-23  |  17KB  |  482 lines

  1.       Assembly Language for Veggies (And C programmers)      Part 5.
  2.  
  3. Welcome to 1992! It is now several months since the last ASMVEG series...  In
  4. this time I have been learning a bit about Graphics on the PC, and mucking
  5. about with Turbo Pascal, however it has now come time to again put words
  6. onscreen about dear old Assembler once more...
  7.  
  8. Last issue, we looked at The TSR, and started mentioning some tricky things
  9. that are important to programming TSRs...  This issue i'd like to delve into
  10. some simpler work by presenting some simple routines for doing "Workhorse"
  11. stuff - ya know, stuff you take for granted like screen clearing and file
  12. reading/writing etc etc which everyone always seems to assume you know..
  13.  
  14. Oh, if you have a WordProcessor there with adjustable tabstops, set them to 20
  15. spaces between tabs or the listings will look shitty!
  16.  
  17. OK, here goes...
  18.  
  19.  
  20. Screen Clear
  21. ------------
  22.  
  23. A simple routine for a simple job: Clears the screen in the current screen
  24. mode. Homes cursor on text screens, homes ligical cursor on graphics screens.
  25.  
  26. Clear_screen:         push ax
  27.          mov ah,0fh
  28.          int 010h
  29.          mov ah,0
  30.          int 010h
  31.          pop ax
  32.          ret
  33.  
  34. Very easy! Does all the usual jazz like resetting the colours to their
  35. defaults etc. This is a standard sort of thing that I use in just about every
  36. program I can ever remember writing...  it works, it's reliable, and let's
  37. face it, who wants to clear the screen faster??
  38.  
  39.  
  40. Go "Beep"
  41. ---------
  42.  
  43. Yet another rediculous task. Make a beep! This beep is the standard PC beep,
  44. such as you get when you type a text file full of CTRL-G's to the screen or
  45. fill uo your keyboard buffer, and is instantly recognisable as the work of the
  46. BIOS..
  47.  
  48. Go_Beep:         push ax
  49.          push bx
  50.          mov ah,0eh
  51.          mov al,07
  52.          mov bh,0
  53.          int 010h
  54.          pop bx
  55.          pop ax
  56.          ret
  57.  
  58. Call this as often as you like, but remember that your whole program is paused
  59. for the length of the tone.
  60.  
  61.  
  62. What Video?
  63. -----------
  64.  
  65. Ever get sick of asking users their video card type? Why not auto-detect it
  66. yourself and TELL them what you detected...  simple as pie! These video bios
  67. functions were built in to assist the programmer and take the hassle of asking
  68. the user what his card is.. buggered if I know why game writers don't just use
  69. this stuff themselves.... maybe they're stupid C programmers?
  70.  
  71. Detect_VGA:         mov ax,01a00h
  72.          int 010h
  73.          cmp al,01ah
  74.  
  75.          ( if AL=0a1h, then VGA is present )
  76.  
  77. If you have a MCGA (PS/2) system, this will detect the MCGA. To differentiate
  78. between MCGA and true VGA is a difficult thing..  if you specificly want to do
  79. something other than 320x200x256 mode then you'll be needing to detect a SVGA
  80. anyhow, so it doesn't really matter.
  81.  
  82. Detect_EGA:         mov ah,012h
  83.          mov bl,010h
  84.          int 010h
  85.          cmp bl,010h
  86.  
  87.          ( if BL=010h then EGA is NOT present )
  88.  
  89. NB: if BL is not 010h, then it will indicate this:
  90.  
  91.  BL = 0,  64k EGA RAM
  92.  BL = 1, 128k EGA RAM
  93.  BL = 2, 192k EGA RAM
  94.  BL = 3, 256k EGA RAM
  95.  
  96. WARNING: Use this AFTER Detect_VGA because a VGA will also return this
  97. information as well (After all, a vGA emulates EGA don't it?!?!)
  98.  
  99. OK..  if it's not EGA or VGA then it MUST be either CGA or MONO ... if it's a
  100. mone, the screen MUST be in mode 7, if it's CGA it will be in another mode..
  101.  
  102. Detect_CGA_MONO:         mov ah,0fh
  103.          int 010h
  104.          cmp al,7
  105.  
  106.          ( if AL=7, MONO is present, else must be CGA )
  107.  
  108. Furthermore: if BOTH a MONO and ANY colour card are present, and you want to
  109. make sure, first detect the Default card...  if you find a colour card, try
  110. calling setvideomode and try setting mode 7. Next, read the mode back. if
  111. you're in mode 7, MONO is present. if not, then you only got colour. If you
  112. detect MONO as default and you don't find VGA or EGA, try setting mode 3 to
  113. test for CGA. If you can set mode 3 then CGA is present, but not default.
  114.  
  115.  
  116. KeyPressed?
  117. -----------
  118.  
  119. Moving right along....  the BIOS has some good keypress routines indeed,
  120. in fact I have never needed to do anything keyboardish and not been able to
  121. use the BIOS for it...  oh, and the BIOS is very quick with the keyboard too -
  122. definately suitable for use where high speed is required.
  123.  
  124. Is_A_Key_Pressed:         mov ah,1
  125.          int 016
  126.  
  127. If the Z (Zero) flag is set, then NO keys have been pressed. If the Z flag is
  128. NOT set a key has been pressed. This does not retrieve a key from the keyboard
  129. buffer, it just lets you know there's one there to be read later on.
  130.  
  131.  
  132. Next Key in Buffer
  133. ------------------
  134.  
  135. Retrieve_keypress:         mov ah,0
  136.          int 016
  137.  
  138. This gets the next key that has been pressed and puts the "Main byte" in AL,
  139. and the "Auxiliary Byte" in AH. normally AL holds the ASCII code for the key
  140. pressed, but if the key is not a normal key (like a function or arrow key)
  141. then AL=0 and AH holds the so called EXTENDED keycode... tables of extended
  142. keycodes should be in any good ASM book - Norton's has it for one. Note, if
  143. you call this service BEFORE a key is ready, the routine pauses till one key
  144. is hit, which freezes the program in effect...  saves a look for key, until
  145. pressed, then read key loop though.
  146.  
  147.  
  148. Keyboard Lights (AT Computers ONLY!)
  149. ------------------------------------
  150.  
  151. Ever wanted to stuff with the keyboard lights? Once again the BIOS will help
  152. us there... At absolute memory location 0040:0017 - that's right - the BIOS
  153. data table... 
  154.  
  155. Here is the layout of that byte:
  156.  
  157.   bit#    7      6    5     4      3    2      1      0
  158.        Insert  Caps  Num  Scroll  ALT  CTRL  L.SHI  R.SHI
  159.  
  160. Altering any of these bits will alter the computer's idea of what's what...
  161. changing bits 6-4 will toggle the 3 lights on the KB.. all courtesy of the
  162. BIOS.. neat and quick...  Fiddling with INS changes the INS state, but mucking
  163. with alt, ctrl and the shifts is not on, otherwise you REVERSE the action of
  164. that key; held down becomes like released etc...  if you turned them all
  165. opposite to what they normally are, then to type normally one would have to
  166. hold down ALT, CTRL and both shift keys!!
  167.  
  168.  
  169. Reading a file to memory
  170. ------------------------
  171.  
  172. One of the hardest routines to master is file access. Here it is simplified.
  173.  
  174. Filename         db 'filexxxx.!!!',0
  175. Handle         dw 0
  176. memseg         dw 07000h
  177.  
  178. Load_File:         mov ah,03dh
  179.          mov al,0
  180.          mov dx,offset filename
  181.          int 021h
  182.  
  183. This section opens the file for Read/Write access... changing AL changes the
  184. access thus:
  185.  
  186.    AL = 0    Read/Write
  187.    AL = 1    Write Only
  188.    AL = 2    Read Only
  189.  
  190. Obviously the filename is held in an ASCIIZ string at Filename. ASCIIZ stands
  191. for ASCII with a 0 on the end basicly..  the 0 tells DOS where the end of the
  192. string is.
  193.  
  194.          jc FAIL
  195.  
  196. If carry is set on return, the open operation FAILED. The file must exist and
  197. be able to be opened for this operation to work. An error code will be passed
  198. in AX - again see Norton's or other for errorcode listings.
  199.  
  200.          mov handle,ax
  201.  
  202. DOS has what is called a handle passed into AX if the open was successfull..
  203. each file has a unique handle, and there may be up to the number of files
  204. liste din the FILES= statement in Config.sys open at any one time. note that
  205. StdIn, StdOut, StdErr and Null are always open by DOS and are used when
  206. "piping" program outpout to and from files. (DIR > files.lst for example) so
  207. normally the handle for the fist open file will be 0005. We must store
  208. whatever we get back in any case so this is done.
  209.  
  210. At this stage we have simply requested DOS to get us a file. We haven't read
  211. it yet. 
  212.  
  213. read_from_file:         mov dx,word ptr cs:[memseg]
  214.          push dx
  215.          pop ds
  216.          mov dx,0
  217.          mov ah,03fh
  218.          mov bx,word ptr cs:[handle]
  219.          mov cx,0ffffh
  220.          int 021h
  221.          jc FAIL
  222.          cmp ax,0ffffh
  223.          jnz end_read
  224.  
  225.          mov dx,word ptr cs:[memseg]
  226.          add dx,01000h
  227.          mov word ptr cs:[memseg],dx
  228.          jmp read_from_file
  229.  
  230. end_read:         push cs
  231.          pop ds         
  232.  
  233. Now this is quite complex and takes a while to understand.... read up on how
  234. the registers are bieng used... basicly the file is loaded in 64k chunks
  235. (Because that's the biggest DOS can do in one go) to the 64k chunk of memory
  236. located at DS:DX. This program happens to hard code the load address at 07000h
  237. but normally you'd change that to the place you'd requested from DOS. It also
  238. assumes to start at offset 0 in that segment...  change DX if you start part
  239. way into the segment. The routine attempts to load 64k; and will load up to
  240. the limit of a less-than-64k file. Again, C is set if there is an error same
  241. as the open routine. Next, AX holds the bytes read. if AX is less than 0ffffh
  242. then less than 64k was read and we're at the end of the file. If so, jump out.
  243. If not, we increment the memory segment and jump out.
  244.  
  245. Note that DS has to be changed to suit the routine, thus the use of CS:
  246. override... the CS override makes sure the data we're storing does in the
  247. right segment (remember that normally DS=CS, but since we're changing DS, we
  248. must override the normal use of DS and make it use CS so it looks in the right
  249. segment)
  250.  
  251. At this stage our file is loaded and memseg holds the final segment of the
  252. file, whilst ax holds the number of bytes in the last segment. simple
  253. subtraction will provide the full file size thus:
  254.  
  255. Loaded file size (in bytes)   =    ((memseg-inital segment)*64k)+ax
  256.  
  257. NB: the final number will be a double word - 32 bits long, so don;t try and
  258. load it into a register, or even work it out this way!!
  259.  
  260. After we are finished with the file we must tell DOS so. We must call the
  261. Close File function to tell dos to return the Handle to the unused pool and
  262. also to save any changes we may have written to the file physicly to disk.
  263. ALWAYS CLOSE THE FILE!!!  Even if you get errors, CLOSE THAT FILE!! This is
  264. the ONLY way to avoid your program making chop suey of the disk drive's files!!
  265.  
  266. Close_File:         mov ah,03eh
  267.          mov bx,handle
  268.          int 021h
  269.  
  270. The file is now closed. Again Carry reports an error, but the only possible
  271. error is ax=6 which is invalid handle (Caused by feeding it a handle number
  272. that is not in use!) otherwise AX = 0 on exit.
  273.  
  274.  
  275.  
  276. Writing Files to disk
  277. ---------------------
  278.  
  279. Writing a file is identical to reading it...  Open the file, write the data,
  280. then close it... just use the different functions as listed in your ASM book.
  281. Use function 3d to write an existing file. Function 3c is used to write a new,
  282. non existant file, or to completely trash the contents of an existing file.
  283.  
  284.  
  285. I/O ports present
  286. -----------------
  287.  
  288. What Serial and Parallel ports are there?  Memory locations 0040:0000 thru
  289. 0040:000F hold the addresses of the first four Serial ad parallel ports viz:
  290.  
  291.  
  292. 0040:0000 | f8 03 | f8 02 | e8 03 | e8 02 | bc 03 | 78 03 | 78 02 | 00 00 |
  293.           | COM1: | COM2: | COM3: | COM4: | LPT1: | LPT2: | LPT3: | LPT4: |
  294.  
  295. So, for example, to find the address of LPT1:, simply code:
  296.  
  297.          push ds
  298.          mov ax,040h
  299.          push ax
  300.          pop ds
  301.          mov dx,word ptr[8]
  302.          pop ds
  303.  
  304. DX now holds the address of LPT1:.  You should remember that these ports are
  305. 16 bit addresses, so use a 16 bit register, and also remember that in PC's the
  306. Most signivigant bit is stored second.
  307.  
  308. If you find 00 00 stored then there are no more ports to be found - in the
  309. example above for example there are but 3 parallel ports. This information is
  310. placed by the BIOS so once again it is quite reliable, and also multitasking
  311. friendly to read these bytes. The only side effect is that sometimes
  312. non-standard serial ports will not show up here (ie serial ports at non
  313. standard addresses) - although drivers that usually come with these ports
  314. usually update this area if needed. BBS Fossil drivers are one such driver
  315. that will, for example.
  316.  
  317.  
  318. Reading AT CMOS Settings
  319. ------------------------
  320.  
  321. Everyone wants to know this!!
  322.  
  323. CMOS_INFO         db 03fh dup(?)
  324.  
  325. Read_CMOS:         push ds
  326.          pop es
  327.          mov cx,03fh
  328.          mov bl,00h
  329.          mov di,offset CMOS_INFO
  330.          cli
  331.  
  332. read_in:         mov dx,0070h
  333.          mov al,bl
  334.          out dx,al
  335.          mov dx,0071h
  336.          in al,dx
  337.          stosb
  338.          inc bl
  339.          loop read_in
  340.          sti
  341.  
  342. This routine basicly outputs a byte reprsenting the byte in the CMOS we want
  343. to read to port 0070h, then reads in the byte from port 0071h. It does this
  344. 03fh times to read the entire CMOS to memory.
  345.  
  346. The Layout of the CMOS is thus:
  347.  
  348. byte#         Funtion
  349.  
  350. Real Time Clock Bytes
  351.  
  352.   0         Current Second in BCD format
  353.   1         Second Alarm in BCD
  354.   2         Current Minuute in BCD
  355.   3         Minute alarm in BCD
  356.   4         Current hour in BCD
  357.   5         Hour alarm in BCD
  358.   6         Current day of week in BCD
  359.   7         Current date in BCD
  360.   8         Current month in BCD
  361.   9         Current year in BCD
  362.  
  363. Status bytes
  364.  
  365.   a,b,c,d         Status bytes A,B,C & D
  366.  
  367. System configuration
  368.  
  369.   e         Diagnostic Status
  370.   f         ShutDown Reason
  371.  10         Diskette drive types where:
  372.          bit 7-4 drive 0 (A:)  bit 3-0 drive 1 (B:) where
  373.            0000b = none
  374.            0001b = 360k
  375.            0010b = 1.2M
  376.            0011b = 720k
  377.            0100b = 1.44M
  378.  
  379.  11         fixed disk drive 0 type (0 = none, 1-46 = type)
  380.  12         fixed disk drive 1 type (0 = none, 1-46 = type)
  381.  
  382.  13         reserved
  383.  
  384.  14         equipment byte where:
  385.          bit 7-6 = number of drives, where 00b = 1, 01b = 2
  386.          bit 5-4 = display, where:
  387.            00b = reserved
  388.            01b = cga 40 cols
  389.            10b = cga 80 cols
  390.            11b = cga in mono mode
  391.          bit 3-2 reserved
  392.          bit 1 = math co present
  393.          bit 0 = diskette drive present
  394.  
  395.  15         Base memory in k, low byte
  396.  16         Base memory in k, high byte
  397.  17         Extended memory in k, low byte
  398.  18         Extended memory in k, high byte
  399.  
  400.  19         disk type of first fixed disk
  401.  1a         disk type of second fixed disk
  402.  
  403.  1b-2dh         reserved
  404.  
  405.  2e         high byte checksum of bytes 10-2dh
  406.  2f         low byte checksum of bytes 10-2dh
  407.  
  408.  30         Low byte actual Extended memory size
  409.  31         high byte actual Extended memory size
  410.  
  411.  32         century in BCD
  412.  
  413.  33         information flag
  414.  
  415.  34-3f         reserved
  416.  
  417. This list is based on an early phoenix BIOS. Newer bios's wil have the
  418. reserved areas changed, and any bytes after 2fh are fair game.. Use this info
  419. at your own peril because ther is no guarantee of manufacturer compatability -
  420. Compaq and amstrad bieng but two known misconformers. All BIOS's with "Type
  421. 47" user Hard Drive types will undoubtedly be non-standard too.
  422.  
  423. BCD Refers to binary coded decimal number format. This format is made to store
  424. the numbers 0-9 only. Imagine hex, but just omit the letters.. you got BCD..
  425.  
  426. Viz:   8d = 00001000 bcd
  427.       11d = 00101000 bcd
  428.       99d = 10011001 bcd
  429.       47d = 01000111 bcd
  430.  
  431. Not as efficient bit-wize as binary (the biggest 8 bit number in BCD is 99)
  432. but simple to decode - split into high and low nibbles and treat as binary.
  433.  
  434.  
  435. FastWrite String to Screen
  436. --------------------------
  437.  
  438. Sick of DOS int 21h function 09h write string? Try this one - it's a BIOS
  439. string writer that's about twice as fast as DOS.. you may find it worth using
  440. for although it's longer than dear old dos into 21, it's surely miles the
  441. quicker! It is designed as a "drop in" replacement for dos int 21, function
  442. 09, and takes the same setup, ie $ terminated string pointed to by DS:DX. All
  443. registers are preserved in this routine.
  444.  
  445.  
  446. write_bios_string:         push ax
  447.          push bx
  448.          push si
  449.          mov si,dx
  450.  
  451. loop_write:         lodsb
  452.          cmp al,'$'
  453.          jz exit_write
  454.  
  455.          mov ah,0eh
  456.          mov bx,0
  457.          int 010h
  458.          jmp loop_write
  459.  
  460. exit_write:         pop si
  461.          pop bx
  462.          pop ax
  463.          ret
  464.  
  465.  
  466. ------------------------------------------------------------------------------
  467.  
  468. Err...  well that kinda brings to a close this ASMVEG...  I've brought to
  469. light a few routines I was meaning to hand out long ago, and added a couple
  470. more I just thought of :-)
  471.  
  472. Next time round i'll probably have some more code in runnable form, and will
  473. be looking at a specific program .. i'm not sure exactly what yet :-) but it
  474. will be coming... Perhaps we'll look at making musical sounds and perhaps we
  475. will look at low level disk structures or something...  i'm not exactly sure
  476. yet....
  477.  
  478. Anyhow, until the next VEG, keep hacking!
  479.  
  480.                            .\\erlin
  481.  
  482.